import gym
from gym import error, spaces, utils
from gym.utils import seeding

import pandas as pd
# from  action import *

# from object_create import lp_state,vm_state

##s输出下一个状态


# cpu_state=['cpu0','cpu1','cpu2','cpu3','cpu4','cpu5','cpu6','cpu7','cpu8','cpu9','cpu10','cpu11','cpu12','cpu13','cpu14','cpu15','cpu16','cpu17','cpu18','cpu19','cpu20','cpu21','cpu22','cpu23','cpu24','cpu25','cpu26','cpu27','cpu28','cpu29','cpu30','cpu31','cpu32','cpu33','cpu34','cpu35','cpu36','cpu37','cpu38','cpu39','cpu40','cpu41','cpu42','cpu43','cpu44','cpu45','cpu46','cpu47','cpu48','cpu49','cpu50','cpu51','cpu52','cpu53','cpu54','cpu55','cpu56','cpu57','cpu58','cpu59','cpu60','cpu61','cpu62','cpu63','cpu64','cpu65','cpu66','cpu67','cpu68','cpu69','cpu70','cpu71','cpu72','cpu73','cpu74','cpu75','cpu76','cpu77','cpu78','cpu79','cpu80','cpu81','cpu82','cpu83','cpu84','cpu85','cpu86','cpu87','cpu88','cpu89','cpu90','cpu91','cpu92','cpu93','cpu94','cpu95','cpu96','cpu97','cpu98','cpu99']
# mem_state=['mem0','mem1','mem2','mem3','mem4','mem5','mem6','mem7','mem8','mem9','mem10','mem11','mem12','mem13','mem14','mem15','mem16','mem17','mem18','mem19','mem20','mem21','mem22','mem23','mem24','mem25','mem26','mem27','mem28','mem29','mem30','mem31','mem32','mem33','mem34','mem35','mem36','mem37','mem38','mem39','mem40','mem41','mem42','mem43','mem44','mem45','mem46','mem47','mem48','mem49','mem50','mem51','mem52','mem53','mem54','mem55','mem56','mem57','mem58','mem59','mem60','mem61','mem62','mem63','mem64','mem65','mem66','mem67','mem68','mem69','mem70','mem71','mem72','mem73','mem74','mem75','mem76','mem77','mem78','mem79','mem80','mem81','mem82','mem83','mem84','mem85','mem86','mem87','mem88','mem89','mem90','mem91','mem92','mem93','mem94','mem95','mem96','mem97','mem98','mem99']
import numpy as np


class LoadEnv(gym.Env):
    def __init__(self):

        low1 = np.zeros((3, 100))

        text1 = np.ones((2, 100))
        text2 = np.ones((1, 100)) * 8

        high1 =  np.vstack((text1, text2))
        high1=np.array((high1))
        self.observation_space = spaces.Box(low=low1, high=high1, shape=(3, 100), dtype=np.float32)
        # self.observation_space = spaces.Dict({
        #     # "obj_num": spaces.Box(low=self.min_obj, high=self.max_obj,shape=(len(self.node),1),dtype=np.uint8),
        #     "cpu_usage": spaces.Box(low=self.min_usage, high=self.max_usage,shape=(len(self.node),1))
        # })
        # self.action_space = spaces.MultiDiscrete(
        #    [10,10]
        # )
        self.action_space = spaces.Discrete(10)
        self.seed()

    def seed(self, seed=None):
        self.np_random, seed = seeding.np_random(seed)
        return [seed]

    # def step(self, action):
    def step(self, action):

        lp_state = self.state
        vm_state = self.getvmstate()
        vm_num_index = np.argsort(np.negative(vm_state[2]))  ######对虚拟机的lp数量进行降序，并求出降序后的索引
        lp_cpu_index = np.argsort(np.negative(lp_state[0]))  ######对lp的cpu进行降序，并求出降序后的索引
        max_vm = vm_num_index[0]  ######最大lp数量的虚拟机的编号
        min_vm = vm_num_index[8]  ######最小lp数量的虚拟机的编号
        # print(vm_num_index)
        # for action in range(10):
        # list=np.where(lp_location == max_vm)
        # list1 = [lp_cpu[i] for i in np.array(list)]
        # print(list.shape)
        index1 = np.where(lp_state[2] == max_vm)  ##最大cpu节点上的lp编号
        index2 = index1[0]  ##最大cpu节点上的lp编号
        lp_cpu1 = lp_state[0][index2] ##最大cpu节点上的lp的cpu


        # print(np.sum(lp_cpu1))

        lp_cpu_index1 = np.argsort(np.negative(lp_cpu1))  ######最大cpu节点上的lp的cpu降序索引

        index3 = index2[lp_cpu_index1] #############最大cpu节点上lp的cpu降序编号




        if len(index3) > action:


            # lp_location1 = lp_state[2]  #每个lp的位置

            vm_cpu1=vm_state[0]    #每个节点的cpu利用率
            vm_mem1=vm_state[1]  #每个节点的mem利用率
            vm_num1=vm_state[2]    #每个节点的lp数量


            vm_cpu1[max_vm]-= np.sum(lp_state[0][index3[0:action + 1]])  ###最大节点的cpus下降
            vm_cpu1[min_vm]+= np.sum(lp_state[0][index3[0:action + 1]]) ####最小节点的cpu增加
            vm_mem1[max_vm]-=np.sum(lp_state[1][index3[0:action + 1]])
            vm_mem1[min_vm] += np.sum(lp_state[1][index3[0:action + 1]])
            vm_num1[max_vm]-=action
            vm_num1[min_vm] += action
            # print("max: ",vm_cpu_max)
            # print("min: " ,vm_cpu_min)
            lp_state[2][index3[0:action+1 ]] = min_vm  ####将前action个lp的位置改为最小的虚拟机
            next_state = lp_state[0], lp_state[1], lp_state[2]
            vm_state=vm_cpu1,vm_mem1,vm_num1
            self.state=next_state
            # reward=next_state[5][max_vm]/next_state[5][min_vm]
            reward=self.getreward()
            # print(reward)
            done = False
        if len(index3) < action:
            done=True
        return self.state, reward, done, {}  # 返回状态、奖励、和don

    def getreward(self):
        vm_state=self.getvmstate()
        reward = -(np.max(vm_state[0]) / np.average(vm_state[0]))
        return reward
    def getdata(self,file):
        p=open(file)
        q=pd.read_csv(p)
        state=q.apply(pd.to_numeric, errors='coerce')
        return state
    def getvmstate(self):

        lp_state=self.state
        vm_cpu,vm_mem,vm_num=np.zeros((3,9))
        for i in range(100):
            for j in range(9):
                if lp_state[2][i]==j:
                    vm_num[j]+=1
                    vm_cpu[j]+=lp_state[0][i]
                    vm_mem[j]+=lp_state[1][i]
        vm_state = vm_cpu, vm_mem, vm_num
        return vm_state







    def reset(self):

        lp_state=self.getdata("lp_state.csv")

        lp_state1=lp_state.loc[1]


        lp_cpu, lp_mem, lp_location = np.zeros((3, 100))

        for i in range(100):
            lp_cpu[i] = lp_state1["cpu%s" % i]
            lp_mem[i] = lp_state1["mem%s" % i]
            lp_location[i] = lp_state1["vm_loc%s" % i]


        self.state=np.array((lp_cpu,lp_mem,lp_location))##初始化状态为lp+vm



        return self.state
    def render(self, mode='human', close=False):
        """
        It may be called periodically to print a rendition of the environment. This could
        be as simple as a print statement, or as complicated as rendering a 3D
        environment using openGL. For this example, we will stick with print statements.
        """
        # Render the environment to the screen
        # print(f'Step: {self.state}')
        # print(f'action: {self.action}')
        print(f'Balance: {self.getreward()}')
        # print(f'Shares held: {self.shares_held} (Total sold: {self.total_shares_sold})')
        # print(f'Avg cost for held shares: {self.cost_basis} (Total sales value: {self.total_sales_value})')
        # print(f'Net worth: {self.net_worth} (Max net worth: {self.max_net_worth})')


